/*
 * A lowlevel_init function that sets up the stack to call a C function to
 * perform further init.
 *
 * (C) Copyright 2010
 * Texas Instruments, <www.ti.com>
 *
 * Author :
 *	Aneesh V	<aneesh@ti.com>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <asm-offsets.h>
#include <config.h>
#include <linux/linkage.h>

ENTRY(lowlevel_init)
	/*
	 * Setup a temporary stack. Global data is not available yet.
	 * #define CONFIG_SYS_INIT_SP_ADDR \
	 *	(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)
	 * 初始栈定义到了 内部的sram中
	 */
	ldr	sp, =CONFIG_SYS_INIT_SP_ADDR # 初始栈地址存入 sp
	bic	sp, sp, #7 /* 8-byte alignment for ABI compliance 低三位清零，8字节对齐，为了 abi调用规范*/
#ifdef CONFIG_SPL_DM /*  未定义 */
	mov	r9, #0
#else
	/*
	 * Set up global data for boards that still need it. This will be
	 * removed soon.
	 */
#ifdef CONFIG_SPL_BUILD
	ldr	r9, =gdata
#else
	sub	sp, sp, #GD_SIZE # 预留一块 GD_SIZE大小的栈
	bic	sp, sp, #7 # 8-byte 对齐
	mov	r9, sp # 将这个位置存储在 r9 中，代表着gd
#endif
#endif
	/*
	 * Save the old lr(passed in ip) and the current lr to stack
	 * lr 即 bl	cpu_init_crit 时存储的地址，因为接下来要调用 别的函数了，会被覆盖
	 * ip 是 old lr
	 */
	push	{ip, lr}

	/*
	 * Call the very early init function. This should do only the
	 * absolute bare minimum to get started. It should not:
	 *
	 * - set up DRAM
	 * - use global_data
	 * - clear BSS
	 * - try to start a console
	 *
	 * For boards with SPL this should be empty since SPL can do all of
	 * this init in the SPL board_init_f() function which is called
	 * immediately after this.
	 */
	bl	s_init # 啥也没做
	pop	{ip, pc} # pop实际执行顺序是与push相反的，先出栈存储到了 pc 也即 lr存储到 pc，而 ip的旧值存储到ip
ENDPROC(lowlevel_init)
